/**
 * Copyright (c) 2006 Amgad S Youssef
 * All Rights Reserved.
 * Licensed under the Eclipse Public License - v 1.0
 * For more information see http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipsejcde.core.builder;

import java.util.ArrayList;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipsejcde.core.IChecker;
import org.eclipsejcde.core.ICheckerStatus;
import org.eclipsejcde.core.JCDECore;
import org.eclipsejcde.core.builder.checkers.AppletAIDChecker;
import org.eclipsejcde.core.builder.checkers.DuplicateAIDChecker;
import org.eclipsejcde.core.builder.checkers.JCProjectPropertiesChecker;
import org.eclipsejcde.core.builder.checkers.PackageAIDChecker;

/**
 * @author Amgad S Youssef
 *
 */
public class JavacardBuilder extends IncrementalProjectBuilder {

	protected ArrayList<IChecker> checkers;

	public JavacardBuilder() {
		checkers = new ArrayList<IChecker>();
		initializeCheckers();
	}

	protected void initializeCheckers() {
		addChecker(new JCProjectPropertiesChecker());
		addChecker(new DuplicateAIDChecker());
		addChecker(new PackageAIDChecker());
		addChecker(new AppletAIDChecker());
	}

	protected void addChecker(IChecker checker) {
		checkers.add(checker);
	}

	protected String getMarkerID() {
		return JCDECore.MARKER_TYPE;
	}

	private void checkResource(IResource resource) throws CoreException {
		for (int i = 0; i < checkers.size(); i++) {
			ICheckerStatus[] checkerStatusArr = checkers.get(i).check(resource);
			for (int j = 0; j < checkerStatusArr.length; j++) {
				if (checkerStatusArr[j].getSeverity() != IStatus.OK) {
					addMarker(resource, checkerStatusArr[j]);
					IStatus[] statusArr = checkerStatusArr[j].getChildren();
					if (statusArr != null && statusArr.length > 0) {
						for (int k = 0; k < statusArr.length; k++) {
							addMarker(((ICheckerStatus) statusArr[k]).getResource(), (ICheckerStatus) statusArr[k]);
						}
					}
				}
			}
		}
	}

	private void addMarker(IResource resource, ICheckerStatus checkerStatus) throws CoreException {
		if (resource instanceof IProject) {
			addMarker((IProject) resource, checkerStatus.getMessage(), checkerStatus.getSeverity());
		} else if (resource instanceof IFolder) {
			addMarker((IFolder) resource, checkerStatus.getMessage(), checkerStatus.getSeverity());
		} else if (resource instanceof IFile) {
			addMarker((IFile) resource, checkerStatus.getMessage(), checkerStatus.getCharStart(), checkerStatus.getCharEnd(), checkerStatus.getSeverity());
		} else {
			addMarker(resource, checkerStatus.getMessage(), checkerStatus.getSeverity());
		}
	}

	private void addMarker(IResource resource, String message, int severity) throws CoreException {
		IMarker marker = resource.createMarker(getMarkerID());
		marker.setAttribute(IMarker.MESSAGE, message);
		marker.setAttribute(IMarker.SEVERITY, severity);
	}

	private void addMarker(IProject project, String message, int severity) throws CoreException {
		IMarker marker = project.createMarker(getMarkerID());
		marker.setAttribute(IMarker.MESSAGE, message);
		marker.setAttribute(IMarker.SEVERITY, severity);
	}

	private void addMarker(IFolder folder, String message, int severity) throws CoreException {
		IMarker marker = folder.createMarker(getMarkerID());
		marker.setAttribute(IMarker.MESSAGE, message);
		marker.setAttribute(IMarker.SEVERITY, severity);
	}

	private void addMarker(IFile file, String message, int charStart, int charEnd, int severity) throws CoreException {
		IMarker marker = file.createMarker(getMarkerID());
		marker.setAttribute(IMarker.MESSAGE, message);
		marker.setAttribute(IMarker.SEVERITY, severity);
		if (charStart > -1 && charEnd > charStart) {
			marker.setAttribute(IMarker.CHAR_START, charStart);
			marker.setAttribute(IMarker.CHAR_END, charEnd);
		}
	}

	@Override
	protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException {
		getProject().deleteMarkers(getMarkerID(), false, IResource.DEPTH_INFINITE);
		getProject().accept(new ResourceVisitor());
		return null;
	}

	private class ResourceVisitor implements IResourceVisitor {

		public ResourceVisitor() {
			super();
		}

		@Override
		public boolean visit(IResource resource) throws CoreException {
			checkResource(resource);
			// return true to continue visiting children.
			return true;
		}
	}

}
